/*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#include <sourcemod>
#include <sdktools>
#include <l4d_stocks>

#include "macros.sp"
#include "helpers.sp"

new bool:on_ride[MAXCLIENTS] = { false, ...};
new has_victim[MAXCLIENTS] = { -1, ...};
new bool:has_pressed[MAXCLIENTS] = { false, ... }; //store if jockey already tryed double jump

new Handle:cvar_jockeypounce_power = INVALID_HANDLE;
new Handle:cvar_jockeypounce_mult = INVALID_HANDLE;
new Handle:cvar_jockeyjump_power = INVALID_HANDLE;

new bool:can_double_jump[MAXCLIENTS] = { false, ... };

public OnPluginStart()
{

	cvar_jockeypounce_power = CreateConVar("l4d2_jockeypounce_power", "400.0", "How many force is applied on high when jockey pounce");
	cvar_jockeypounce_mult = CreateConVar("l4d2_jockeypounce_mult", "0.2", "How many force is multiplied when jockey pounce");
	cvar_jockeyjump_power = CreateConVar("l4d2_jockeyjump_power", "500", "How many force is applied when jockey jump");
	HookEvent("player_hurt", event_player_hurt);
	HookEvent("jockey_ride", event_jockey_ride);
	HookEvent("jockey_ride_end", event_jockey_ride_end);

	AutoExecConfig(true, "l4d2_jockeypounce");
}

public OnMapStart()
{
	for(new i=0; i < MAXCLIENTS; i++)
	{
		on_ride[i] = false;
		can_double_jump[i] = false;
		has_victim[i] = -1;
		has_pressed[i] = false;
	}
}

public Action:event_player_hurt(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));

	if(IsValidSurvivorAlive(client) && on_ride[client] == false)
	{
		new attack = GetClientOfUserId(GetEventInt(event, "attacker"));

		/*fast filter only infected*/
		if(IsValidInfectedAlive(attack))
		{
			/*now check if it's a jockey*/
			decl String:wep[32];
			GetEventString(event, "weapon", wep, sizeof(wep));
			if(strcmp(wep, "jockey_claw") == 0)
			{
				/* use ability */
				turn_head_to(client, attack);
			}
		}
	}
}

public Action:event_jockey_ride(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	new victim = GetClientOfUserId(GetEventInt(event, "victim"));

	if(IsValidSurvivorAlive(victim) && IsValidInfectedAlive(client))
	{
		on_ride[victim] = true;
		has_victim[client] = victim;
		has_pressed[client] = false;

		//get velocity from player
		decl Float:velocity[3];
		GetEntPropVector(client, Prop_Data, "m_vecVelocity", velocity);
		decl Float:velocity_victim[3];
		GetEntPropVector(victim, Prop_Data, "m_vecVelocity", velocity_victim);

		/* get speed to make a big pounce*/
		new Float:speed = GetVectorLength(velocity);

		velocity[2] = GetConVarFloat(cvar_jockeypounce_power);
		velocity[0] += (speed * GetConVarFloat(cvar_jockeypounce_mult));
		velocity[1] += (speed * GetConVarFloat(cvar_jockeypounce_mult));
		
		new Float:finalVec[3]
		AddVectors(velocity, velocity_victim, finalVec);

		TeleportEntity(victim, NULL_VECTOR, NULL_VECTOR, finalVec); // should pounce on ghost bomb ^^ */
		/*double jump can only be made 0.5sec after pounce */
		can_double_jump[client] = false;
		CreateTimer(0.5, active_doublejump, client, TIMER_FLAG_NO_MAPCHANGE);
		CreateTimer(0.7, desactive_doublejump, client, TIMER_FLAG_NO_MAPCHANGE);
	}
}

public Action:event_jockey_ride_end(Handle:event, const String:name[], bool:dontBroadcast)
{
	new victim = GetClientOfUserId(GetEventInt(event, "victim"));
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	
	if(IsValidSurvivor(victim))
	{
		on_ride[victim] = false;
	}

	if(IsValidInfected(client))
	{
		has_victim[client] = -1;
		has_pressed[client] = false;
	}
}


public Action:active_doublejump(Handle:timer, any:client)
{
	can_double_jump[client] = true;
}

public Action:desactive_doublejump(Handle:timer, any:client)
{
	can_double_jump[client] = false;
}

public Action:OnPlayerRunCmd(client, &buttons)
{
	if(!IsValidHumanInfectedAlive(client))
		return;

	if(has_victim[client] == -1)
		return;

	if(buttons & IN_JUMP)
	{

		decl Float:velocity[3];
		GetEntPropVector(has_victim[client], Prop_Data, "m_vecVelocity", velocity);

		/* 2 case, when first auto pounce, and when normal jockey jump */

		/* first case, 1sec after the first pounce, make another one */
		if((can_double_jump[client] && !has_pressed[client]) || velocity[2] == 0)
		{	
			velocity[2] = GetConVarFloat(cvar_jockeyjump_power);			
			TeleportEntity(has_victim[client], NULL_VECTOR, NULL_VECTOR, velocity);

			if(can_double_jump[client])
			{
				PrintToChatAllExclude(client, has_victim[client], "\x01Jockey \x04%N\x01 made a double jump \x040.5\x01 sec after pounce !", client);
				PrintToChatOnly(client, has_victim[client], "\x01Jockey \x05%N\x01 made a double jump \x050.5\x01 sec after pounce !", client);
			}

		}

		has_pressed[client] = true;
	}

}